#ifndef _IP_H_
#define _IP_H_

#include <crt_util.h>

#ifdef __cplusplus
extern "C" {
#endif

// sizeof(iphdr_t) = 20
typedef struct iphdr_s {
#if BYTE_ORDER == LITTLE_ENDIAN
    uint8_t ihl : 4; // ip header length
    uint8_t version : 4;
#elif BYTE_ORDER == BIG_ENDIAN
    uint8_t version : 4;
    uint8_t ihl : 4;
#else
#error "BYTE_ORDER undefined!"
#endif
    uint8_t tos;      // type of service
    uint16_t tot_len; // total length
    uint16_t id;
    uint16_t frag_off; // fragment offset
    uint8_t ttl;       // Time To Live
    uint8_t protocol;
    uint16_t check; // checksum
    uint32_t saddr; // srcaddr
    uint32_t daddr; // dstaddr
    /*The options start here.*/
} iphdr_t;

static_inline uint16_t checksum(uint8_t* buf, int len)
{
    unsigned int sum = 0;
    uint16_t* ptr = (uint16_t*)buf;
    while (len > 1) {
        sum += *ptr++;
        len -= 2;
    }
    if (len) {
        sum += *(uint8_t*)ptr;
    }
    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);
    return (uint16_t)(~sum);
};

#ifdef __cplusplus
}
#endif

#endif //_IP_H_
